/*
 *  Copyright 2010 Susanta Tewari.
 *  This file is part of genomemap.
 * 
 *  genomemap is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  genomemap is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with genomemap.  If not, see <http://www.gnu.org/licenses/>.
 */
package genomemap.map;

import genomemap.data.GWData;
import genomemap.lhood.physical.PLikeliHood;
import genomemap.map.ContigMap.Contig;
import java.util.List;

/**
 * A data object
 * @version 1.0 Apr 9, 2010
 * @author Susanta Tewari
 */
public class ProbeMap extends Map {

    /**
     * estimates spacings between probes
     */
    private SizeEstimator sizeEstimator;

    public ProbeMap(Integer linkageGroup, List<String> probes) {
        super(linkageGroup, probes);
    }

    public ProbeMap(Integer linkageGroup,
            List<String> labels, String title) {

        super(linkageGroup, labels, title);
    }

    public List<String> getProbes() {
        return labels;
    }

    public Double estimateChromosomeSize() {

        return getSizeEstimator().size();
    }

    public Double estimateContigSize(Contig contig) {

        return getSizeEstimator().size(contig);
    }

    public Double getProbeGap(String probe) {
        return getSizeEstimator().getProbeGap(probe);
    }

    private SizeEstimator getSizeEstimator() {

        if (sizeEstimator == null) sizeEstimator = new SizeEstimator(this);

        return sizeEstimator;
    }

    private class SizeEstimator {

        private final List<Double> probeSpacings;

        private final Integer probeLength = GWData.getInstance().getProbeLength();

        private SizeEstimator(ProbeMap probeMap) {

            PLikeliHood pHood = new PLikeliHood(probeMap);
            probeSpacings = pHood.getProbeSpacing();

        }

        private Double size() {

            double result = 0;

            for (Double spacing : probeSpacings) result += spacing;

            result += getProbes().size() * probeLength;

            return result;
        }

        private Double size(Contig contig) {

            double result = 0;

            int startIndex = labels.indexOf(contig.getStartProbe());
            int endIndex = labels.indexOf(contig.getEndProbe());

            for (int i = startIndex; i <= endIndex; i++) result += probeSpacings.get(i);

            result += contig.getProbes().size() * probeLength;

            return result;
        }

        /**
         * The gap between this probe and the next one. If this is the last one, then throws
         * exception.
         * @param contig
         * @return
         */
        private Double getProbeGap(String probe) {

            int probeIndex = labels.indexOf(probe);

            if (probeIndex == labels.size() - 1) throw new RuntimeException(
                        "illegal access: probe is the last on the map");

            return probeSpacings.get(probeIndex);
        }

    }
}
